﻿using ApiLib.AppStart;
using ApiLib.Helpers;
using ApiLib.Models;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;

namespace ApiLib.Controllers;

/// <summary>
/// 用户角色和权限
/// </summary>
public abstract class BaseRoleController<TR, TU> : BaseController
    where TR : SysRole, new() where TU : SysRoleUser, new()
{
    /// <summary>
    /// 权限配置
    /// </summary>
    protected virtual AbstractBaseAuthorization BaseAuthorization =>
        GlobalConfig.BaseAuthorization ?? throw new Exception("请先配置权限");

    /// <summary>
    /// 所有的角色列表
    /// </summary>
    /// <returns></returns>
    public virtual List<TR> RoleList()
    {
        return Db.Queryable<TR>().ToList();
    }

    /// <summary>
    /// 权限字符串列表
    /// </summary>
    /// <returns></returns>
    public virtual List<RolePermission> PermissionList()
    {
        return BaseAuthorization.GetRolePermissions();
    }

    /// <summary>
    /// 权限信息
    /// </summary>
    /// <returns></returns>
    public virtual TR RoleInfo(int roleId)
    {
        return Db.Queryable<TR>().InSingle(roleId);
    }

    /// <summary>
    /// 角色有哪些用户
    /// </summary>
    /// <returns></returns>
    public virtual List<TU> RoleUsers(int roleId)
    {
        var role = Db.Queryable<TR>().InSingle(roleId);
        if (role == null)
        {
            throw ActionException("角色不存在");
        }

        return GetRoleUsers(role);
    }

    /// <summary>
    /// 获取当前用户的所有权限
    /// </summary>
    /// <returns></returns>
    public virtual HashSet<string> MyPermissions()
    {
        if (BaseUser?.IsSuperAdmin() ?? false)
        {
            return BaseAuthorization.GetAllPermissions();
        }

        return GetCurrentUser()?.GetPermissions() ?? [];
    }

    /// <summary>
    /// 获取角色用户
    /// </summary>
    /// <param name="role"></param>
    /// <returns></returns>
    protected virtual List<TU> GetRoleUsers(TR role)
    {
        return Db.Queryable<TU>()
            .LeftJoin<SysUserinfo>((user, info) => user.UserId == "" + info.Id)
            .Where((user, info) => user.RoleId == role.Id)
            .Select((user, info) => new TU()
            {
                Id = user.Id.SelectAll(),
                UserName = info.Username
            }).ToList();
    }

    /// <summary>
    /// 用户有哪些角色
    /// </summary>
    /// <returns></returns>
    public virtual List<TR> Roles(string userTypeId)
    {
        var baseUser = GetUser(userTypeId);
        if (baseUser == null)
        {
            throw ActionException("用户不存在");
        }

        return Db.Queryable<TR>()
            .InnerJoin<TU>((role, user) => role.Id == user.RoleId)
            .Where((role, user) => user.UserId == Sid)
            .Select((role, user) => role)
            .ToList();
    }

    /// <summary>
    /// 新增角色
    /// </summary>
    /// <param name="role"></param>
    /// <returns></returns>
    public virtual int Save(TR role)
    {
        CheckPerm(BaseAuthorization.SsSave);
        role.CreateUser = Sid;
        role.UpdateUser = Sid;
        role.InitSaveUser();

        SaveRole(role);
        Db.Insertable(role).ExecuteCommand();
        return role.Id;
    }

    /// <summary>
    /// 保存用户
    /// </summary>
    /// <param name="role"></param>
    protected virtual void SaveRole(TR role)
    {
    }

    /// <summary>
    /// 保存权限：个人权限或者角色权限的保存
    /// </summary>
    /// <param name="userTypeIds">更新用户权限需要，同时角色对象里传递Permissions</param>
    /// <param name="roleId">角色ID</param>
    /// <returns></returns>
    public virtual int SaveUsers(int roleId, [FromQuery] string userTypeIds = "")
    {
        CheckPerm(BaseAuthorization.SsSaveUsers);

        var role = Db.Queryable<TR>().InSingle(roleId);
        if (role == null)
        {
            throw ActionException("权限不存在");
        }

        var users = userTypeIds.Split(",").Select(userTypeId => Trance(role.Id, userTypeId)).ToList();
        Db.Insertable(users).ExecuteCommand();
        Flush(role);
        return role.Id;
    }

    /// <summary>
    /// 保存权限：个人权限或者角色权限的保存
    /// </summary>
    /// <param name="userTypeIds">更新用户权限需要，同时角色对象里传递Permissions</param>
    /// <param name="roleId">角色ID</param>
    /// <returns></returns>
    public virtual int RemoveUsers(int roleId, [FromQuery] string userTypeIds = "")
    {
        CheckPerm(BaseAuthorization.SsSaveUsers);

        var role = Db.Queryable<TR>().InSingle(roleId);
        if (role == null)
        {
            throw ActionException("权限不存在");
        }

        var users = userTypeIds.Split(",").ToList();
        Db.Deleteable<TU>().Where(user => user.RoleId == roleId && users.Contains(user.UserId)).ExecuteCommand();
        Flush(role);
        return role.Id;
    }

    /// <summary>
    /// 角色用户
    /// </summary>
    /// <param name="roleId"></param>
    /// <param name="userId"></param>
    /// <returns></returns>
    protected virtual TU Trance(int roleId, string userId)
    {
        return new TU()
        {
            RoleId = roleId,
            UserId = userId,
            CreateUser = Sid
        };
    }

    /// <summary>
    /// 删除权限
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public virtual bool Delete(int id)
    {
        CheckPerm(BaseAuthorization.SsSave);
        var first = Db.Queryable<TR>().First(r => r.Id == id);
        if (first == null)
        {
            throw ActionException("不存在");
        }

        DeleteRole(first);
        Db.Deleteable<TR>().Where(role => role.Id == id).ExecuteCommand();
        return true;
    }

    /// <summary>
    /// 删除角色
    /// </summary>
    /// <param name="tr"></param>
    protected virtual void DeleteRole(TR tr)
    {
    }

    /// <summary>
    /// 检查权限
    /// </summary>
    /// <param name="perm"></param>
    protected virtual void CheckPerm(string perm)
    {
        if (BaseUser == null)
        {
            throw ActionException("没有权限");
        }

        if (!BaseUser.IsSuperAdmin() && !string.IsNullOrEmpty(perm))
        {
            var hasPerm = BaseUser.GetPermissions()?.Contains(perm) ?? false;
            if (!hasPerm)
            {
                throw ActionException("没有权限");
            }
        }
    }

    private void Flush(SysRole role)
    {
        var users = Db.CopyNew().Queryable<SysRoleUser>()
            .Where(user => user.RoleId == role.Id)
            .Select(user => user.UserId)
            .ToList();
        if (users.Count > 0)
        {
            Flush(users);
        }
    }

    private void Flush(List<string> userTypeIds)
    {
        foreach (var userTypeId in userTypeIds)
        {
            Flush(userTypeId);
        }
    }

    private void Flush(string userTypeId)
    {
        DbHelper.FlushUser(userTypeId);
    }
}

/// <summary>
/// 角色权限
/// </summary>
public class RolePermission
{
    /// <summary>
    /// 名称
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// 权限
    /// </summary>
    public string Permission { get; set; }

    /// <summary>
    /// 分组
    /// </summary>
    public string Group { get; set; }

    /// <summary>
    /// 分组名
    /// </summary>
    public string GroupName { get; set; }
}